/**
 * Copyright (C) 2021 All rights reserved.
 *
 * @file dp_trie_ip.h
 * @author Wang Haibin
 * @email wanghaibin@qiyi.com
 * @date Wed Aug  7 21:04:11 CST 2024
 * @brief ip字典树
 */
#pragma once

#include <memory>
#include <vector>

namespace dp {

class dp_trie_ip_node {
public:
    dp_trie_ip_node();
    ~dp_trie_ip_node();

public:
    std::shared_ptr<dp_trie_ip_node> children_[2]; // 存储二进制0和1对应的子节点
    void* data_;                                   // 用户设置的节点值
};

class dp_trie_ip {
public:
    dp_trie_ip();
    ~dp_trie_ip();

    /**
     * @brief 插入cidr数据到树中
     *
     * @param cidr 要插入的cidr, cidr格式: ip/mask
     * @param value 对应的数据value,查询时命中则返回此内容
     * @return true 成功, false 插入失败, 非cidr格式或value为NULL
     */
    bool insert(const std::string& cidr, void* value);

    /**
     * @brief 查找ip_str对应的最接近的value
     *
     */
    void* search(const std::string& ip_str);

private:
    /**
     * @brief 将ip转为四字节整数数组
     *
     * @param ip_str要转换的ip字符串
     * @param ip 存放转换后的ip, 4个元素则为ipv6, 1个元素则为ipv4
     * @param bv6 返回ip是否为ipv6
     * @return true 成功, false ip_str非ip字符串
     */
    bool ip2integer(const std::string& ip_str, std::vector<unsigned int>& ip, bool* bv6);

    /**
     * @brief 解析cidr
     *
     * @param cidr 要解析的cidr字符串
     * @param ip 返回解析到的ip
     * @param mask 解析到的mask长度
     * @param bv6 返回cidr中的ip是否为ipv6
     * @return true 成功转换, false 转换失败
     */
    bool parse_cidr(const std::string& cidr, std::vector<unsigned int>& ip,
        int& mask, bool* bv6);

private:
    std::shared_ptr<dp_trie_ip_node> root_; // 根节点
};

} // namespace dp
